import jsSHA from 'jssha'
import bfconsole from "../utils/bf-console";
import bfelem from './bf-element'
import dateFormat from 'dateformat'
import bfi18n from './bf-i18n'
import bfstore, {state} from './bf-store'
import uuid from 'uuid/v1'
import bfevent from '../utils/bf-event'
import bfWs from './bf-websocket'

export default {
    sha256(in_str, type = "B64") {
        var shaObj = new jsSHA("SHA-256", "TEXT");
        shaObj.update(in_str);
        return shaObj.getHash(type);
    },
    //ms_status hex to bin
    ms_status_hex2bin(ms_status) {
        if (ms_status.length < 12) {
            ms_status = "000000000000"
        }
        return this.hex2bin(ms_status)
    },
    // 二进制、十六进制转换
    toHex(obj) {
        if (typeof obj !== "number") {
            bfconsole.error('the param must be number:', obj);
            return obj;
        }
        var str = parseInt(obj).toString(16);
        str = this.padStringWithLeadingZero(str, 2);
        return str.toUpperCase();
    },
    hex2bin(hex) {
        var bytes = [];
        for (var i = 0; i < hex.length - 1; i += 2) {
            bytes.push(parseInt(hex.substr(i, 2), 16));
        }
        return bytes;
    },
    // 字符串不足指定长度，则在前面补0
    padStringWithLeadingZero(orig_str, str_len) {
        var result = orig_str;
        while (result.length < str_len) {
            result = '0' + result
        }
        return result
    },
    // DMRID 编码、解析
    dmrid2ssbbccmm(hex_dmr_id) {
        var ssbbccmm = {
            pp: 0,
            ss: 0,
            bb: 0,
            cc: 0,
            mm: 0,
            ok: false
        };

        if (hex_dmr_id.length != 8) {
            return ssbbccmm
        }

        var bin_dmr_id = this.hex2bin(hex_dmr_id);
        ssbbccmm.pp = bin_dmr_id[0] & 0x7f;
        ssbbccmm.ss = (bin_dmr_id[1] & 0xf8) >> 3;
        ssbbccmm.bb = ((bin_dmr_id[1] & 0x07) << 2) | ((bin_dmr_id[2] & 0xc0) >> 6);
        ssbbccmm.cc = (bin_dmr_id[2] & 0x3e) >> 1;
        ssbbccmm.mm = (bin_dmr_id[2] & 0x01) * 256 + bin_dmr_id[3];
        ssbbccmm.ok = true;

        return ssbbccmm
    },
    ssbbccmm2dmrid(ss, bb, cc, mm, is_group, pp) {
        var bin_dmr_id_0 = 0;
        if (is_group !== 0) {
            bin_dmr_id_0 = 0x80;
        }
        if (typeof pp !== 'undefined') {
            bin_dmr_id_0 |= pp;
        }
        var bin_dmr_id_1 = ((ss << 3) | (bb >> 2)) & 0xff;
        var bin_dmr_id_2 = (((bb & 0x03) << 6) | (cc << 1) | (mm >> 8)) & 0xff;
        var bin_dmr_id_3 = mm & 0xff;

        return this.padStringWithLeadingZero(bin_dmr_id_0.toString(16).toUpperCase(), 2) +
            this.padStringWithLeadingZero(bin_dmr_id_1.toString(16).toUpperCase(), 2) +
            this.padStringWithLeadingZero(bin_dmr_id_2.toString(16).toUpperCase(), 2) +
            this.padStringWithLeadingZero(bin_dmr_id_3.toString(16).toUpperCase(), 2);

    },
    encodeDMRID(bb, cc, mm, is_group) {
        if (bb === "" && cc === "" && mm === "") {
            return "";
        }
        if (bb == "") {
            bb = 0
        }
        if (cc == "") {
            cc = 0
        }
        if (mm == "") {
            mm = 0
        }
        return this.ssbbccmm2dmrid(parseInt(state.systemInfo.sysId), parseInt(bb), parseInt(cc), parseInt(mm), is_group, parseInt(state.salerId));
    },
    // 计算经纬度半径差值
    calculateLatitudeRadiusDiff(radius) {
        return (radius / 1.85).toFixed(0);
    },
    calculateLongitudeRadiusDiff(lat, radius) {
        var lat_rad = lat * 0.017453292519444;
        return (radius / 1.85 / Math.cos(lat_rad)).toFixed(0);
    },
    LonDiff2Radius(lon_diff) {
        var lon_diff_int = parseInt(lon_diff);
        return (lon_diff_int * 1.85).toFixed(0);
    },
    // 检测浏览器是否是移动端
    isPC() {
        var userAgent = window.navigator.userAgent.toLowerCase();
        var isPC = userAgent.match(/(iPhone|iPod|Android|ios|iPad|Mobile)/i) == null ? true : false;

        return isPC;
    },
    // 检测登录用户权限
    testPermissions(orgRid, type = 'rw') {
        // @orgRid,需要检测权限的组织，@type,检测权限的类型，为crwx=(8,4,2,1)
        // 没有传入组织的rid，或者是默认组织的rid，则不允许编辑数据，返回false
        if (!orgRid || orgRid == 100) {
            bfelem.warningBox(bfi18n.t('notify.notWrite'), "warning");
            return false
        }

        // 读取用户的组织权限数据，通过判断是否有编辑权限
        let userRid = state.userInfo.originData.rid.toString();
        let userAllPerms = state.userPerm[userRid];
        let userPermItem = userAllPerms[orgRid];

        // 对比是否某一权限权，没有提示弹出警告框提示
        let testPerm = (userPerm, perm, msg) => {
            if ((userPerm & perm) == perm) {
                return true
            } else {
                bfelem.warningBox(bfi18n.t(`notify.${msg}`), "warning");
                return false
            }
        };

        // 查找并判断上级权限数据
        let testParentPerm = (_orgRid) => {
            // 通过当前检测的组织找到上级组织的rid，再检测上级组织的权限
            let parentId = bfstore.getters.getParentIdByOrgRid(_orgRid);
            if (parentId) {
                parentId = parentId.toString();
            } else {
                return false;
            }
            userPermItem = userAllPerms[parentId];

            return startTest(parentId);
        };

        // 如果用户没有该组织的权限数据，则向上查找父级权限
        let startTest = (_orgRid) => {
            if (userPermItem) {
                let userPerm = userPermItem.userPerm;
                switch (type) {
                    case "r":
                        // 只读
                        return testPerm(userPerm, 4, "notWrite");
                    case "rx":
                        // 只读、下发命令
                        return testPerm(userPerm, 5, "notWrite");
                    case "rw":
                        return testPerm(userPerm, 6, "notWrite");
                    case "rwx":
                        // 可读写、下发命令
                        return testPerm(userPerm, 7, "notWrite");
                    case "cr":
                        // 只读、包含下级
                        return testPerm(userPerm, 12, "notWrite");
                    case "crx":
                        // 只读、包含下级、下发命令
                        return testPerm(userPerm, 13, "notWrite");
                    case "crw":
                        // 可读写、包含下级
                        return testPerm(userPerm, 14, "notWrite");
                    case "crwx":
                        // 全权限,可读写、包含下级、下发命令
                        return testPerm(userPerm, 15, "notWrite");
                    default:
                        return false;
                }
            } else {
                return testParentPerm(_orgRid);
            }
        };

        return startTest(orgRid);
    },
    // 检测正在编辑数据的操作用户是否默认用户
    testRootUser() {
        if (state.userInfo.originData.rid.eq(100)) {
            bfelem.warningBox(bfi18n.t("notify.rootUser"), "warning");
            return true
        } else {
            return false
        }
    },
    // 检测正在编辑的用户数据是否自己
    testEditSelfData(editRid) {
        if (state.userInfo.originData.rid.eq(editRid)) {
            bfelem.warningBox(bfi18n.t("notify.notEditSelf"), "warning");
            return true
        } else {
            return false
        }
    },
    // 获取设备视口宽度级别
    layoutLevel() {
        let level = 4;
        if (window.innerWidth >= 1920) {
            level = 5;
        } else if (window.innerWidth >= 1200) {
            level = 4;
        } else if (window.innerWidth >= 992) {
            level = 3;
        } else if (window.innerWidth >= 768) {
            level = 2;
        } else {
            level = 1;
        }
        return level;
    },
    // 自定义下载文件功能
    saveAsFile(filename, data, mimetype) {
        var defaultMime = "application/octet-stream";
        var blob = new Blob([data], {type: mimetype || defaultMime});
        if (window.navigator.msSaveOrOpenBlob) {
            window.navigator.msSaveBlob(blob, filename);
        } else {
            var elem = window.document.createElement('a');
            elem.href = window.URL.createObjectURL(blob);
            elem.download = filename;
            document.body.appendChild(elem);
            elem.click();
            document.body.removeChild(elem);
        }
    },
    downloadFile(url, filename, mimetype) {
        var ajax = new XMLHttpRequest();
        ajax.open("GET", url, true);
        ajax.responseType = 'blob';
        ajax.onload = (e) => {
            this.saveAsFile(filename, e.target.response, mimetype);
        };
        setTimeout(function () {
            ajax.send();
        }, 0);
    },
    // 判断导出的表格单元格内容是否全是数字，如果是则在字符串前加"'"
    conversionTableNumber(str) {
        if (!str) {
            return ""
        }
        if (!isNaN(str)) {
            str = "'" + str;
        } else {
            str = "" + str;
        }
        return str;
    },
    // 处理导出的dataTable 表头和数据
    getTableHead(head, detailHead) {
        let __head = '<tr>';
        let i = 0;
        // 如果导出的数据有子表，导出的表头则从1开始
        if (detailHead) {
            i = 1;
        }
        for (; i < head.length; i++) {
            let item = head[i];
            __head += "<th>" + item.title + "</th>";
        }
        __head += "</tr>";
        return __head;
    },
    getTableBody(head, body, detailHead, processZero, detailBodyName) {
        let __body = "";
        let __index = 1;
        for (let k in body) {
            let item = body[k];
            __body += '<tr>';
            __body += "<td>" + __index + "</td>";
            let i = 1;
            // 如果导出的数据有子表，导出的表格数据则从2开始
            if (detailHead) {
                i = 2;
            }
            for (; i < head.length; i++) {
                let __head = head[i];
                let __name = __head.data;
                let __data = item[__name];

                // 处理导出数据中全是数字的单元格内容被清除前面的零的问题
                __body += "<td>" + (processZero ? this.conversionTableNumber(__data) :
                    __data) + "</td>";
            }
            __body += "</tr>";
            // 加载详情表 table
            if (detailHead) {
                __body += this.getTableHead(detailHead);
                __body += this.getTableBody(detailHead, item[detailBodyName], false, processZero);
            }
            // 递增索引序号
            __index++;
        }
        return __body;
    },
    // 导出 dataTable 数据到 excel 表格
    exportTableData(head, body, detailHead, detailBodyName) {
        if (body.length < 1) {
            bfelem.messageBox(bfi18n.t("notify.noData"), 'warning');
            return false;
        }
        var html = "<table border='1'>";
        html += this.getTableHead(head, detailHead);
        html += this.getTableBody(head, body, detailHead, true, detailBodyName);
        html += "</table>";
        this.saveAsFile('bf_' + (this.nowLocalTime().replace(/\s|-|:/ig, "")) + '.xls', html);
    },
    // 读取或储存离线数据
    getLocalStorage(key) {
        return window.localStorage.getItem(key);
    },
    setLocalStorage(key, value) {
        if (typeof value !== 'string') {
            value = JSON.stringify(value);
        }
        window.localStorage.setItem(key, value);
    },
    removeLocalStorage(key) {
        window.localStorage.removeItem(key);
    },
    // 创建浏览器桌面消息通知
    onSiteNotify(data, click_callback) {
        bfconsole.log('display web notification');

        let opts = {
            title: "",
            message: ""
        };
        if (typeof data === "string") {
            opts.title = "";
            opts.message = data || "a message!";
        } else {
            // title = device.selfId + " / ";
            // if (device.userName) {
            //   title += device.userName + " / "
            // }
            // title += device.orgShortName;
            // message = device.promptContent;
            notify = Object.assign(opts, data);
        }
        let callback = typeof click_callback === "function" ? click_callback : function () {
        };
        let notify = {
            title: "",
            message: "a message",
            type: 'info',
            duration: 5 * 1000,
            offset: 25,
            onClick: callback
        };
        notify = Object.assign(notify, opts);
        bfelem.notifyBox(notify);
    },
    onDestopNotify(data, click_callback) {
        let that = this;
        let __defaultLogo = require('../assets/bfdxLogo.png');
        let options = {
            body: "",
            data: {},
            tag: "",
            icon: __defaultLogo
        };
        let title = "";
        if (typeof data === "string") {
            options = Object.assign(options, {
                body: data,
                tag: data
            });
        } else {
            options = Object.assign(options, data);
        }

        let notification = new Notification(title, options);
        notification.onshow = () => {
            // 5秒后关闭通知
            setTimeout(notification.close.bind(notification), data.time || 5000);
        };
        notification.onerror = (err) => {
            // 发生错误，转为调用站内通知
            bfconsole.error("notification error", notification, err);
            that.onSiteNotify(data, click_callback);
        };
        if (typeof click_callback === 'function') {
            notification.onclick = click_callback;
        }
    },
    createNotify(data, click_callback) {
        // 浏览器不把持桌面通知，转为创建站内通知
        if (!window.Notification) {
            bfconsole.error("浏览器不支持桌面通知或全屏中被屏蔽");
            this.onSiteNotify(data, click_callback);
            return
        }
        // 检测浏览器是否有权限显示桌面通知，没有则申请
        if (window.Notification && Notification.permission !== "granted") {
            Notification.requestPermission(function (result) {
                if (result !== 'granted') {
                    this.onSiteNotify(data, click_callback);
                } else {
                    this.onDestopNotify(data, click_callback);
                }
            }.bind(this));
        } else {
            // 获取到权限，创建桌面通知
            this.onDestopNotify(data, click_callback);
        }
    },
    // 使用 dateFormat 插件格式化时间
    nowLocalTime(date = new Date()) {
        return dateFormat(new Date(date), "yyyy-mm-dd HH:MM:ss");
    },
    nowUtcTime(date = new Date()) {
        return dateFormat(new Date(date), "UTC:yyyy-mm-dd HH:MM:ss");
    },
    utcTimeConvertToLocalTime(time) {
        if (!time) {
            time = this.nowUtcTime();
        }
        let timeOffset = new Date().getTimezoneOffset() * 60 * 1000;
        time = Date.parse(new Date(time));
        time = new Date(time - timeOffset);
        return dateFormat(new Date(time), "yyyy-mm-dd HH:MM:ss");
    },
    localTimeConvertToUtcTime(time) {
        return dateFormat(new Date(time), "UTC:yyyy-mm-dd HH:MM:ss");
    },
    // 获取指定日期的时间字符串，如获取当前时间前一个月时间
    getTimeBySpecifyDate(option) {
        let opts = {
            date: new Date(),
            mod: "mm",
            offset: 1,
            type: "local"
        };
        if (!option || typeof option !== 'object') {
            option = {};
        }
        opts = Object.assign(opts, option);
        let _date = new Date(opts.date);
        switch (opts.mod) {
            case "yy":
                _date = _date.setFullYear(_date.getFullYear() + opts.offset);
                break;
            case "dd":
                _date = _date.setDate(_date.getDate() + opts.offset);
                break;
            case "HH":
                _date = _date.setHours(_date.getHours() + opts.offset);
                break;
            case "MM":
                _date = _date.setMinutes(_date.getMinutes() + opts.offset);
                break;
            case "SS":
                _date = _date.setSeconds(_date.getSeconds() + opts.offset);
                break;
            case "mm":
            default:
                _date = _date.setMonth(_date.getMonth() + opts.offset);
        }
        _date = new Date(_date);

        return opts.type == "local" ?
            dateFormat(_date, "yyyy-mm-dd HH:MM:ss") :
            opts.type == "utc" ? this.localTimeConvertToUtcTime(_date) : "";
    },

    // 重置网站标题
    setWebSiteTitle() {
        document.title = bfi18n.t("header.siteTitle");
    },
    // 将图片转成base64格式URL
    getBase64Image(image) {
        let dataURL = "";
        try {
            var canvas = document.createElement("canvas");
            canvas.width = image.width;
            canvas.height = image.height;

            var ctx = canvas.getContext("2d");
            ctx.drawImage(image, 0, 0, image.width, image.height);
            var ext = image.src.substring(image.src.lastIndexOf(".") + 1).toLowerCase();
            dataURL = canvas.toDataURL("image/" + ext);
        } catch (err) {
            bfconsole.error("load base64 image error:", err);
        }
        return dataURL;
    },
    // 读取文件内容API,bfFileReader(param).then(result=>{}).catch(err=>{})
    bfFileReader(file, mode = "url", size = 10 * 1024) {
        return new Promise((resolve, reject) => {
            try {
                if (file.size > size) {
                    bfelem.messageBox(bfi18n.t("notify.sizeUpperLimit"), 'error');
                    reject(0);
                    return false
                }
                var reader = new FileReader();
                reader.onload = (ev) => {
                    resolve(ev.target.result);
                };
                reader.onerror = (err) => {
                    reject(err);
                };
                switch (mode) {
                    case "url":
                        reader.readAsDataURL(file);
                        break;
                    case "str":
                        reader.readAsBinaryString(file);
                        break;
                    case "buf":
                        reader.readAsArrayBuffer(file);
                        break;
                    case "txt":
                        reader.readAsText(file, 'gb2312');
                        break;
                }
            } catch (err) {
                reject(err);
            }
        });
    },
    // 向目标函数添加新的方法
    addNewFunc(targetFn, ...newFn) {
        return () => {
            typeof targetFn === 'function' && targetFn();
            for (let i = 0; i < newFn.length; i++) {
                typeof newFn[i] === 'function' && newFn[i]();
            }
        };
    },
    searchTreeNodeByKeyword(el = "#tree", filter = "") {
        var tree = $(el).fancytree("getTree");
        if (!filter) {
            // 清空筛选功能
            tree.clearFilter();
            return;
        }
        tree.filterNodes(function (node) {
            return new RegExp(filter, "ig").test(node.data.filterValue);
        }, tree.options.filter);
    },
    // 生成一个指定长度的随机字符串
    randomUuid(len = 10) {
        let str = Math.random().toString(36).substr(2);
        for (; str.length < len;) {
            str += Math.random().toString(36).substr(2);
        }
        return str.slice(0, len);
    },
    bfuuid() {
        return uuid().replace(/-/ig, "");
    },

    // 表单验证规则方法
    required(trigger = "blur") {
        return {
            required: true,
            message: bfi18n.t("formRules.required"),
            trigger: trigger
        }
    },
    inputLengthLimit(num = 16, trigger = 'blur') {
        return {
            max: num,
            message: bfi18n.t("formRules.limitCharacter", {num}),
            trigger: trigger
        }
    },
    mustNumber(trigger = 'blur') {
        return {
            validator: (rule, value, callback) => {
                let reg = /^\d+$/;
                if (value !== "" && !reg.test(value)) {
                    callback(new Error(bfi18n.t("formRules.mustNumber")));
                } else {
                    callback();
                }
            }, trigger: trigger
        }
    },
    timeValidity(fromTime, toTime) {
        let result = true;
        let _date = this.getTimeBySpecifyDate({
            date: fromTime,
            mod: "mm",
            offset: 6
        });

        if (fromTime >= toTime || toTime > new Date(_date).getTime()) {
            result = false;
        }

        return result
    },

    // 登录成功后处理服务器的响应数据
    afterLogined(sessionId, userData) {
        bfstore.commit("setLogined", true);
        bfstore.commit("resetSsId", sessionId);
        let userInfo = {
            name: userData.loginName,
            originData: userData,
            setting: JSON.parse(userData.setting),
            permission: 7
        };
        bfstore.commit("saveUserInfo", userInfo);
        bfWs.requestUserPermissionOrg(state.userInfo.originData.rid, 1);

        // 添加登录成功日志
        bfevent.once("bflogLoaded", () => {
            bfevent.emit("addLog", "logs.loginSuccess");
        });
    },

    getDefaultsAvatar() {
        return ""
    },
    getDefaultsOrgLogo() {
        return ""
    },
    // 字符串与unit8Array相互转换
    toUTF8Array(str) {
        let utf8 = [];
        for (let i = 0; i < str.length; i++) {
            let charcode = str.charCodeAt(i);
            if (charcode < 0x80) utf8.push(charcode);
            else if (charcode < 0x800) {
                utf8.push(0xc0 | (charcode >> 6),
                    0x80 | (charcode & 0x3f));
            }
            else if (charcode < 0xd800 || charcode >= 0xe000) {
                utf8.push(0xe0 | (charcode >> 12),
                    0x80 | ((charcode >> 6) & 0x3f),
                    0x80 | (charcode & 0x3f));
            }
            // surrogate pair
            else {
                i++;
                // UTF-16 encodes 0x10000-0x10FFFF by
                // subtracting 0x10000 and splitting the
                // 20 bits of 0x0-0xFFFFF into two halves
                charcode = 0x10000 + (((charcode & 0x3ff) << 10)
                    | (str.charCodeAt(i) & 0x3ff));
                utf8.push(0xf0 | (charcode >> 18),
                    0x80 | ((charcode >> 12) & 0x3f),
                    0x80 | ((charcode >> 6) & 0x3f),
                    0x80 | (charcode & 0x3f));
            }
        }
        return utf8;
    },
    fromUTF8Array(data) { // array of bytes
        let str = '', i;

        for (i = 0; i < data.length; i++) {
            let value = data[i];

            if (value < 0x80) {
                str += String.fromCharCode(value);
            } else if (value > 0xBF && value < 0xE0) {
                str += String.fromCharCode((value & 0x1F) << 6 | data[i + 1] & 0x3F);
                i += 1;
            } else if (value > 0xDF && value < 0xF0) {
                str += String.fromCharCode((value & 0x0F) << 12 | (data[i + 1] & 0x3F) << 6 | data[i + 2] & 0x3F);
                i += 2;
            } else {
                // surrogate pair
                let charCode = ((value & 0x07) << 18 | (data[i + 1] & 0x3F) << 12 | (data[i + 2] & 0x3F) << 6 | data[i + 3] & 0x3F) - 0x010000;

                str += String.fromCharCode(charCode >> 10 | 0xD800, charCode & 0x03FF | 0xDC00);
                i += 3;
            }
        }

        return str;
    },

    // unit8Array 异或操作，参数必须为unit8Array类型
    bfXor(encrypt, key) {
        let j = 0;
        for (let i = 0; i < encrypt.length; ++i) {
            encrypt[i] = encrypt[i] ^ key[j];
            ++j;
            if (j == key.length) {
                j = 0;
            }
        }

        return encrypt;
    }
}
